package com.longkier.gx_library_springboot.Service;

import com.longkier.gx_library_springboot.entity.Book;
import com.longkier.gx_library_springboot.exception.CustomException;
import com.longkier.gx_library_springboot.repository.BookRepository;
import com.longkier.gx_library_springboot.utils.FileUploadUtils;
import com.longkier.gx_library_springboot.utils.RequestUtils;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class BookService {

    private static final Logger logger = LoggerFactory.getLogger(BookService.class);
    private final BookRepository bookRepository;

    /**
     * 新增图书
     * @param book 图书实体
     * @return 是否成功
     */
    public boolean addBook(Book book, MultipartFile file) {
        try {
            book.setBookNumber(generateUniqueBookNumber());
            if (file != null && !file.isEmpty()){// 上传封面并保存返回文件路径
                String bookCover = FileUploadUtils.saveFile(file, book.getBookNumber());
                book.setBookCover(bookCover); // 设置图书封面地址
            }
            book.setBookStatus("可借");
            book.setUpdateTime(LocalDateTime.now());
            book.setCreateTime(LocalDateTime.now());
            bookRepository.save(book);
            return true;
        } catch (IOException e) {
            logger.error("文件上传失败: {}", e.getMessage());
            throw new CustomException(500, "上传图书封面失败");
        }catch(Exception e){
               throw new CustomException(404, "图书添加出现错误");
        }
    }

    /**
     * 批量删除图书。
     *
     * @param bookId 要删除的图书 ID 列表
     * @return 如果删除成功，返回 删除数量；否则返回 false
     */
    @Transactional
    public boolean batchDeleteUsers(@Param("bookId") List<Long> bookId) {
        if (bookId == null || bookId.isEmpty()) {
            return false;
        }
        // 获取要删除的图书列表
        List<Book> booksToDelete = bookRepository.findByBookIdIn(bookId);
        // 删除每个图书的封面文件
        for (Book book : booksToDelete) {
            try {
                // 检查封面路径是否为空
                String bookCover = book.getBookCover();
                if (bookCover != null && !bookCover.isEmpty()) {
                    FileUploadUtils.deleteFile(bookCover);
                }
            } catch (IOException e) {
                logger.error("删除文件失败: {}", e.getMessage());
                throw new CustomException(500, "删除图书封面失败");
            }
        }
        // 批量删除图书记录
        int deletedCount = bookRepository.deleteAllByIdInBatch(bookId);
        return deletedCount == bookId.size();
    }


    /**
     * 分页获取图书列表。
     *
     * @param page 当前页码（从 0 开始）
     * @param size 每页大小
     * @param bookNumber 图书编号（可选）
     * @param bookName 图书名（可选）
     * @param bookAuthor 图书作者名称（可选）
     * @param bookArea 图书区位（可选）
     * @param bookType 图书类型（可选）
     * @param bookStatus 图书状态（可选）
     * @return 图书分页对象
     */
    public Page<Book> getBooksServices(int page, int size,
                                       String bookNumber,
                                       String bookName,
                                       String bookAuthor,
                                       String bookArea,
                                       String bookType,
                                       String bookStatus) {
        Pageable pageable = PageRequest.of(page, size);
        return bookRepository.findByCriteria(bookNumber, bookName, bookAuthor,bookArea,bookType,bookStatus, pageable);
    }

    /**
     * 获取指定图书编号的图书。
     *
     * @param bookNumber 图书编号
     * @return 图书对象
     */
    public Optional<Book> getByBookNumber(String bookNumber) {
        return bookRepository.findByBookNumber(bookNumber);
    }

    /**
     * 更新图书信息
     *
     * @param book 图书实体
     * @return 是否成功
     */
    public boolean updateBook(Book book, MultipartFile file) {
        Optional<Book> existingBook = bookRepository.findById(book.getBookId());
        if (existingBook.isPresent()) {
            try {
                // 如果文件不为空且不是空文件，则上传文件
                if (file != null && !file.isEmpty()) {
                    // 上传封面并保存返回文件路径
                    String bookCover = FileUploadUtils.saveFile(file, bookRepository.getBookNumberByBookId(book.getBookId()).getBookNumber());
                    book.setBookCover(bookCover); // 设置图书封面地址
                }
                book.setBookNumber(existingBook.get().getBookNumber()); // 再次写入原有图书编号
                book.setUpdateTime(LocalDateTime.now()); // 更新时间
                bookRepository.save(book); // 直接保存（包括更新）
                return true;
            } catch (IOException e) {
                throw new CustomException(500, "上传图书封面失败");
            }
        } else {
            throw new CustomException(404, "图书不存在");
        }
    }

    /**
     * 批量设置图书状态。
     *
     * @param userIds 要更新的图书 ID 列表
     * @param status  新的状态
     * @return 如果更新成功，返回 true；否则返回 false
     */
    public boolean batchUpdateStatus(@Param("userIds,status")List<Long> userIds, String status) {
        List<Book> books = bookRepository.findAllById(userIds);
        if (books.isEmpty()) {
            return false;
        }
        books.forEach(book -> {
            book.setBookStatus(status);
            book.setUpdateTime(LocalDateTime.now());
        });
        bookRepository.saveAll(books);
        return true;
    }


    // 随机生成唯一图书编号
    /**
     * 生成唯一的图书编号。
     * - 生成随机图书编号，确保其在数据库中唯一。
     *
     * @return 唯一的图书编号
     */
    public String generateUniqueBookNumber() {
        String BookNumber;
        do {
            BookNumber = RequestUtils.generateRandom11Number();
        } while (bookRepository.existsByBookNumber(BookNumber));
        return BookNumber;
    }
}
